import GameFrameworkModule from "../Base/GameFrameworkModule";
import {IObjectPoolManager} from "./IObjectPoolManager";
import {ObjectPoolBase} from "./ObjectPoolBase";
import Component = cc.Component;
import ccclass = cc._decorator.ccclass;

const DefaultPriority: number = 0;
const DefaultCapacity: number = 99999999;
const DefaultExpireTime: number = Number.MAX_VALUE;
@ccclass("ObjectPoolManager")
export class ObjectPoolManager implements GameFrameworkModule, IObjectPoolManager {
    private readonly _objectPools: Map<string, ObjectPoolBase>;

    Count(): number {
        return this._objectPools.size;
    }

    constructor() {
        this._objectPools = new Map<string, ObjectPoolBase>();
    }

    CreateObjectPool<T extends Component>(type: string | { prototype:T }, capacity?: number): ObjectPoolBase {
        let nodepool: ObjectPoolBase = new ObjectPoolBase(type);
        if(this.HasObjectPool(type)){
            throw new Error("Already exist object pool "+type);
        }
        let classtype:string = undefined;
        if(typeof type === "string"){
            classtype = type;
        }
        if(type instanceof Component){
            classtype = type.constructor.name;
        }else{
            throw new Error("is not extend Component");
        }
        this._objectPools.set(classtype,nodepool);
        return nodepool;
    }


    DestroyObjectPool<T extends Component>(type:  { prototype:T } | string): boolean {
        let classtype:string = undefined;
        if(typeof type === "string"){
            classtype = type;
        }
        if(type instanceof Component){
            classtype = type.constructor.name;
        }else{
            throw new Error("is not extend Component");
        }
        if(!this._objectPools.has(classtype)){
            return false;
        }
        this._objectPools.get(classtype).clear();
        return this._objectPools.delete(classtype);
    }

    GetAllObjectPools(): ObjectPoolBase[] {
        let arr = [];
        this._objectPools.forEach(value => {
            arr.push(value);
        })
        return arr;
    }

    GetObjectPool<T extends Component>(type:  { prototype:T }| string): ObjectPoolBase {
        let classtype:string = undefined;
        if(typeof type === "string"){
            classtype = type;
        }
        if(type instanceof Component){
            classtype = type.constructor.name;
        }else{
            throw new Error("is not extend Component");
        }
        return this._objectPools.get(classtype);
    }


    HasObjectPool<T extends Component>(type:  { prototype:T }| string): boolean {
        let classtype:string = undefined;
        if(typeof type === "string"){
            classtype = type;
        }
        if(type instanceof Component){
            classtype = type.constructor.name;
        }else{
            throw new Error("is not extend Component");
        }
        return this._objectPools.has(classtype);
    }

    get Priority(): number {
        return 980;
    }

    Shutdown(): void {
        this._objectPools.forEach(value => {
            value.clear();
        })
        this._objectPools.clear();
    }

    Update(elapseSeconds: number, realElapseSeconds: number): void {
        // this._objectPools.forEach(value => {
        //        value.Update(elapseSeconds,realElapseSeconds);
        // })
    }

    get baseName(): string {
        return "GameFrameworkModule";
    }

}